package com.gateway.plugin.global;

import com.gateway.common.constant.Constants;
import com.gateway.common.dto.ApiDefinition;
import com.gateway.common.enums.PlatformEnum;
import com.gateway.common.enums.RpcTypeEnum;
import com.gateway.plugin.api.context.GatewayContext;
import com.gateway.plugin.api.context.GatewayContextBuilder;
import com.gateway.plugin.api.context.GatewayContextDecorator;
import com.gateway.plugin.base.cache.ApiDataCache;
import com.gateway.plugin.base.util.ServerWebExchangeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;

import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @program: ahcloud-gateway
 * @description:
 * @author: YuKai Fan
 * @create: 2024/5/20 09:39
 **/
public class DefaultGatewayContextBuilder implements GatewayContextBuilder {

    private static final String RPC_TYPE = "rpc_type";

    private final Map<RpcTypeEnum, GatewayContextDecorator> decoratorMap;

    /**
     * 实例化一个新的默认gateway上下文构建器
     *
     * @param decoratorMap
     */
    public DefaultGatewayContextBuilder(Map<RpcTypeEnum, GatewayContextDecorator> decoratorMap) {
        this.decoratorMap = decoratorMap;
    }

    @Override
    public GatewayContext build(ServerWebExchange exchange) {
        Pair<RpcTypeEnum, ApiDefinition> pair = buildData(exchange);
        return decoratorMap.get(pair.getLeft()).decorator(buildDefaultContext(exchange.getRequest(), pair.getRight()));
    }

    private Pair<RpcTypeEnum, ApiDefinition> buildData(final ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        String rpcType = headers.getFirst(RPC_TYPE);
        // 默认情况下不需要这个参数
        if (StringUtils.isNotBlank(rpcType)) {
            return ImmutablePair.of(RpcTypeEnum.acquireByName(rpcType), new ApiDefinition());
        }
        ApiDefinition apiDefinition = exchange.getAttribute(Constants.API_DATA);
        if (Objects.nonNull(apiDefinition)) {
            exchange.getAttributes().put(Constants.API_DATA, apiDefinition);
            String apiRpcType = apiDefinition.getRpcType();
            if (StringUtils.isNotBlank(apiRpcType)) {
                return ImmutablePair.of(RpcTypeEnum.acquireByName(apiDefinition.getRpcType()), apiDefinition);
            }
        }
        return ImmutablePair.of(RpcTypeEnum.SPRING_CLOUD, new ApiDefinition());
    }

    private GatewayContext buildDefaultContext(final ServerHttpRequest request, ApiDefinition apiDefinition) {
        PlatformEnum platformEnum = ServerWebExchangeUtils.getAppPlatformByRequest(request);
        return GatewayContext.Builder.builder()
                .ipAddress(String.valueOf(request.getRemoteAddress()))
                .origin(request.getHeaders().getOrigin())
                .startDateTime(new Date())
                .method(request.getMethod())
                .platformEnum(platformEnum)
                .build();
    }
}
